package com.vision.interceptors;

import com.vision.config.WebSocketServer;
import com.vision.utils.JwtUtil;
import com.vision.utils.ThreadLocalUtil;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import java.util.Map;

@Component
public class UserAccessControlInterceptor implements HandlerInterceptor {

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    /**
     * 在请求处理之前进行调用（Controller方法调用之前）
     * @param request 请求
     * @param response 响应
     * @param handler 处理器
     * @return 是否放行
     * @throws Exception 异常
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        HttpSession session = request.getSession();
        try {
            // 1. 获取请求头中的 token 并判空
            String token = request.getHeader("Authorization");
            if (token == null) {
                throw new RuntimeException("token 为空");
            }

            // 2. 解析 token
            Map<String, Object> claims = JwtUtil.parseToken(token); // 如果 token 过期则会自动抛出异常
            String username = (String) claims.get("username");

            // 3. 获取 redis 中的 token
            String targetToken = stringRedisTemplate.opsForValue().get(username);

            // 4. 判断 redis 中对应的 token 是否存在
            if (targetToken == null) {
                // 如果 token 不存在，说明用户未登录
                throw new RuntimeException("token 无效");
            }

            // 4.1 将用户信息存入 ThreadLocal 和 session
            ThreadLocalUtil.set(claims); // 存入安全线程
            // 4.2 判断 session 中是否存在 claims
            if (session.getAttribute("claims") == null) {
                session.setAttribute("claims", claims); // 将 claims 存入 session 中
            }

            // 5. 放行
            return true;
        } catch (Exception e) {
            // 4. 如果出现异常，返回 401
            response.setStatus(401);
            // 4.1 清除安全线程
            ThreadLocalUtil.remove();
            // 4.2 清除 session
            session.removeAttribute("claims");
            // 5. 返回 false
            return false;
        }
    }

    /**
     * 在请求处理之后进行调用，但是在视图被渲染之前（Controller方法调用之后）
     * @param request 请求
     * @param response 响应
     * @param handler 处理器
     * @param ex 异常
     * @throws Exception 异常
     */
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        ThreadLocalUtil.remove(); // 清除安全线程
    }
}
